//============================================================================
// Name        : test_exception.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : test_exception in follow more effective item 9-15, Ansi-style
// 1) copy construct will be called when handle exception
// 2) two ExceptionClass will be constructed and pass by value
// 3) catch by value will happen object slicing but catch by reference not
// 4) no throw in deconstruct
// 5) no throw in catch 
//============================================================================

#include <stdio.h>
#include <stdlib.h>
using namespace std;

#include <iostream>

class ExceptionClass{
public:
 ExceptionClass(const char* name="Exception Default Class"){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 ExceptionClass(const ExceptionClass& rhs)
 {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 virtual ~ExceptionClass(){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 virtual void ReportError() {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
};

class ExceptionClassImpl : public ExceptionClass{
public:
 ExceptionClassImpl(const char* name="ExceptionClassImpl Default Class"){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 ExceptionClassImpl(const ExceptionClass& rhs)
 {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 virtual ~ExceptionClassImpl(){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 virtual void ReportError() {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
};

class ExceptionClassBadly : public ExceptionClass{
public:
 ExceptionClassBadly(const char* name="ExceptionClassBadly Default Class"){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 ExceptionClassBadly(const ExceptionClass& rhs)
 {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
 virtual ~ExceptionClassBadly(){
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
	std::bad_alloc exception;
    throw exception;

 }
 virtual void ReportError() {
	cout<<__PRETTY_FUNCTION__<<std::hex<<this<<endl;
 }
};

class ArguClass{
 char* name;
public:
 ArguClass(char* name="default name"){
  cout<<"Construct String::"<<name<<endl;
  this->name=name;
 }
 ~ArguClass(){
  cout<<"Destruct String::"<<name<<endl;
 }
 void mythrow(){
  throw ExceptionClassBadly("my throw");
 }       
};

int main(void) {
 ArguClass e("haha");
 try {
  e.mythrow();
 } 
 catch(int)
 {
  cout<<"If This is Message display screen, This is a Error!!"<<endl;
 }
 #if 0
 // catch by value
 catch(ExceptionClass pTest) 
 {
  pTest.ReportError();
 }
 #endif
  // catch by reference and base class
 catch(ExceptionClass &pTest) 
 {
  pTest.ReportError();
 }
 
 catch(...){
  cout<<"***************"<<endl;  
 }
}